package CapaPersistencia;

import CapaLogica.GestionResort;
import CapaDatos.Cliente;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;


/**
 * Clase de persistencia de implementacion DAO con tecnologia
 * XML para el dominio de Cliente
 *
 */
public class DAOClienteXML implements IDAOCliente {

    /** variable que contiene la raiz del documento Xml*/

    private Element root;
    /** variable que contiene la localizacion del archivo xml*/

    private String fileLocation = "C:/ArchivosXml/Clientes.xml";
    /**
     * constructor por defecto que inicia los valores para trabajar con el documento
     * xml
     */
    public DAOClienteXML() {
        try {
            SAXBuilder builder = new SAXBuilder(false);
            Document doc = null;
            doc = builder.build(fileLocation);
            root = doc.getRootElement();
        } catch (JDOMException ex) {
            System.out.println("No se pudo iniciar la operacion por: " + ex.getMessage());
        } catch (IOException ex) {
            System.out.println("No se pudo iniciar la operacion por: " + ex.getMessage());
        }
    }

    /**
     * firma para pasar un objeto de dominio cliente a un elemento entendible
     * por la libreria jdom para dar soporte al trabajo con xml
     * @param cliente objeto cliente a traducir
     * @return objeto tipo element para el xml
     */
    private Element ClientetoXmlElement(Cliente cliente) {

        Element clienteTrans = new Element("cliente");
        Element userName = new Element("userName");
        userName.setText(cliente.getUserName());
        Element password = new Element("password");
        password.setText(cliente.getPassword());
        Element nombre = new Element("nombre");
        nombre.setText(cliente.getNombre());
        Element apellido = new Element("apellido");
        apellido.setText(cliente.getApellido());
        Element cedula = new Element("cedula");
        cedula.setText(cliente.getCedula());
        Element sexo = new Element("sexo");
        sexo.setText(cliente.getSexo());
        Element fechaNac = new Element("fechaNac");
        fechaNac.setText(cliente.getFechaNac().toString());
        Element edoCivil = new Element("edoCivil");
        edoCivil.setText(cliente.getEdoCivil());
        Element nacionalidad = new Element("nacionalidad");
        nacionalidad.setText(cliente.getNacionalidad());
        Element tipoCliente = new Element("tipoCliente");
        tipoCliente.setText(cliente.getTipoCliente());
        Element numReservas = new Element("numReservas");
        numReservas.setText(String.valueOf(cliente.getNumReservas()));

        clienteTrans.addContent(userName);
        clienteTrans.addContent(password);
        clienteTrans.addContent(nombre);
        clienteTrans.addContent(apellido);
        clienteTrans.addContent(cedula);
        clienteTrans.addContent(sexo);
        clienteTrans.addContent(fechaNac);
        clienteTrans.addContent(edoCivil);
        clienteTrans.addContent(nacionalidad);
        clienteTrans.addContent(tipoCliente);
        clienteTrans.addContent(numReservas);
        return clienteTrans;
    }

    /**
     * firma para pasar de on objeto de tipo elemento a un objeto de dominio
     * para dar soporte a la aplicacion
     * @param element elemento a traducir
     * @return objeto de dominio cliente
     */
    private Cliente clienteToObject(Element element) throws ParseException {
        Cliente cliente = new Cliente();
        cliente.setUserName((element.getChildText("userName")));
        cliente.setPassword((element.getChildText("password")));
        cliente.setNombre((element.getChildText("nombre")));
        cliente.setApellido(element.getChildText("apellido"));
        cliente.setCedula(element.getChildText("cedula"));
        cliente.setSexo(element.getChildText("sexo"));
        cliente.setFechaNac(element.getChildText("fechaNac"));
        cliente.setEdoCivil(element.getChildText("edoCivil"));
        cliente.setNacionalidad(element.getChildText("nacionalidad"));
        cliente.setTipoCliente(element.getChildText("tipoCliente"));
        cliente.setNumReservas(Integer.parseInt(element.getChildText("numReservas")));
        return cliente;
    }

    /**
     * Operacion para guardar en el documento Xml los cambios efectuados
     * @return true si se cumplio la operacion con exito, false en caso contrario
     */
    private boolean updateDocument() {
        try {
            XMLOutputter out = new XMLOutputter();
            FileOutputStream file = new FileOutputStream(fileLocation);
            out.output(root, file);
            file.flush();
            file.close();
            return true;
        } catch (Exception e) {
            System.out.println("error: " + e.getMessage());
            return false;
        }
    }

    /**
     * Operacion que busca un elemento que cumpla con una condicion en el id del xml
     * @param raiz la raiz del documento xml
     * @param dato el dato a comparar para la busqueda del elemento. Debe ser el identificador
     * @return retorna el elemento si existe con la condicion, en caso contrario retorna null
     */
    public static Element buscar(List raiz, String dato) {
        Iterator i = raiz.iterator();
        while (i.hasNext()) {
            Element e = (Element) i.next();
            if (dato.equals(e.getChild("cedula").getText())) {
                return e;
            }
        }
        return null;
    }

    /**
     * firma para agregar un nuevo cliente
     * @param cliente objeto cliente a agregar
     * @return valor boleano con la condicion de exito
     */
    public boolean agregarCliente(Cliente cliente) {
        boolean resultado = false;
        root.addContent(ClientetoXmlElement(cliente));
        GestionResort.getLosClientes().agregarElemento(cliente);
        resultado = updateDocument();
        return resultado;
    }

    /**
     * firma para buscar un cliente
     * @param cedula numero de cedula del cliente a buscar
     * @return objeto cliente con sus datos segun busqueda
     */
    public Cliente buscarCliente(String cedula) {
        Element aux = new Element("cliente");
        List salones = this.root.getChildren("cliente");
        while (aux != null) {
            aux = DAOClienteXML.buscar(salones, cedula);
            if (aux != null) {
                try {
                    return clienteToObject(aux);
                } catch (ParseException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }
        return null;
    }

    /**
     * firma para actualizar un cliente
     * @param cliente objeto cliente a actualizar
     * @return valor boleano con la condicion de exito
     */
    public boolean actualizarCliente(Cliente cliente) {
        boolean resultado = false;
        Element aux = new Element("cliente");
        List salones = this.root.getChildren("cliente");
        while (aux != null) {
            aux = DAOClienteXML.buscar(salones, cliente.getCedula());
            if (aux != null) {
                salones.remove(aux);
                resultado = updateDocument();
            }
        }
        GestionResort.getLosClientes().agregarElemento(cliente);
        agregarCliente(cliente);
        return resultado;
    }

    /**
     * firma para borrar un cliente
     * @param cedula cedula del cliente a borrar
     * @return valor boleano con la condicion de exito
     */
    public boolean borrarCliente(Integer cedula) {
        boolean resultado = false;
        Element aux = new Element("cliente");
        List salones = this.root.getChildren("cliente");
        while (aux != null) {
            aux = DAOClienteXML.buscar(salones, Integer.toString(cedula));
            if (aux != null) {
                salones.remove(aux);
                GestionResort.getLosClientes().eliminarClientePorCedula(cedula);
                System.out.println("Con los clientes eliminados");
                resultado = updateDocument();
            }
        }
        return resultado;
    }

    /**
     * firma para obtener todos los clientes
     * @return ArrayList con todos los objetos cliente
     */
    public ArrayList<Cliente> todosLosClientes() {
        ArrayList<Cliente> resultado = new ArrayList<Cliente>();
        for (Object it : root.getChildren()) {
            Element xmlElem = (Element) it;
            try {
                resultado.add(clienteToObject(xmlElem));
            } catch (ParseException ex) {
                System.out.println(ex.getMessage());
            }
        }
        return resultado;
    }
}